package dmt16.TelemetrySuit.Controller
{
	import dmt16.TelemetrySuit.Communication.PacketReceivedEvent;
	import dmt16.TelemetrySuit.Communication.PacketTypes.DataMessage;
	import dmt16.TelemetrySuit.Communication.PacketTypes.DeviceConfigurationStatus;
	import dmt16.TelemetrySuit.Communication.PacketTypes.InitialisationRequest;
	import dmt16.TelemetrySuit.Communication.PacketTypes.MessageAcknowledge;
	import dmt16.TelemetrySuit.Communication.PacketTypes.PacketReader;
	import dmt16.TelemetrySuit.Communication.PacketTypes.PacketType;
	import dmt16.TelemetrySuit.Communication.PhysicalLayer;
	import dmt16.TelemetrySuit.Communication.SuitTransportLayer;
	import dmt16.TelemetrySuit.Controller.SensorTypes.AccelerometerXSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.AccelerometerYSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.DataFormat;
	import dmt16.TelemetrySuit.Controller.SensorTypes.ElectroLycraSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.FlexSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.ForceSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.GPSModule;
	import dmt16.TelemetrySuit.Controller.SensorTypes.GenericSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.ISensorType;
	import dmt16.TelemetrySuit.Controller.SensorTypes.MMGSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.PulseSensor;
	import dmt16.TelemetrySuit.Controller.SensorTypes.SensorType;
	import dmt16.TelemetrySuit.Controller.SensorTypes.ThermistorSensor;
	import dmt16.TelemetrySuit.UI.GenericSensorTile;
	import dmt16.TelemetrySuit.UI.MainWindow;
	import dmt16.TelemetrySuit.UI.Tiles.AccelerometerTile;
	import dmt16.TelemetrySuit.UI.Tiles.ForceTile;
	import dmt16.TelemetrySuit.UI.Tiles.MMGTile;
	import dmt16.TelemetrySuit.UI.Tiles.PositionTile;
	import dmt16.TelemetrySuit.UI.Tiles.PulseTile;
	import dmt16.TelemetrySuit.UI.Tiles.SpeedTile;
	import dmt16.TelemetrySuit.UI.Tiles.ThermistorTile;
	import dmt16.TelemetrySuit.UI.Tiles.TileBase;
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.sensors.Accelerometer;
	
	public final class Controller
	{
		public static var port:int=5337;
		
		public function Controller()
		{
			PacketReader.instance.addEventListener(PacketReceivedEvent.ON_PACKET_RECEIVED,onPacketReceived);
			SuitTransportLayer.connect(port);
			_mainView.connectBtn.addEventListener(MouseEvent.CLICK,connect);
		}
		
		public function connect(event:Event=null):void{
			trace("Connecting...");
			var init:InitialisationRequest=new InitialisationRequest(null,0);
			SuitTransportLayer.sendPacket(init);
			trace("Connect Request Sent");
		}
		
		public function get connected():Boolean{
			return SuitTransportLayer.connected;
		}
		
		private var _sensors:Vector.<ISensorType>;
		private var _mainView:MainWindow=new MainWindow();
		public function get mainView():MainWindow{
			return _mainView;
		}
		
		public function onPacketReceived(event:PacketReceivedEvent):void{
			switch(event.packet.type){
				case PacketType.DATA_MESSAGE:
					_updateSensors(event.packet as DataMessage);
					break;
				case PacketType.DVC_CONFIG_STATUS:
					_updateDeviceConfig(event.packet as DeviceConfigurationStatus);
					var ack:MessageAcknowledge=new MessageAcknowledge(null,0);
					SuitTransportLayer.sendPacket(ack);
					break;
				case PacketType.MSG_ACK:
					break;
			}
		}
		
		private var _forceLeft:ForceSensor;
		private var _forceRight:ForceSensor;
		
		private var _accelerometerX:AccelerometerXSensor;
		private var _accelerometerY:AccelerometerYSensor;
		
		private var _elycraR:ElectroLycraSensor;
		private var _elycraL:ElectroLycraSensor;
		private var _flexR:FlexSensor;
		private var _flexL:FlexSensor;
		
		private var _mmgL:MMGSensor;
		private var _mmgR:MMGSensor;
		
		private function _updateDeviceConfig(configPacket:DeviceConfigurationStatus):void{
			trace("Received Device Config");
			if(!_gotSensorPacket){
				_sensors=(configPacket as DeviceConfigurationStatus).getConfiguration();
				for each(var s:ISensorType in _sensors){
					switch(s.sensorType){
						case SensorType.FORCE_SENSOR:
							if(_forceLeft==null){
								_forceLeft=s as ForceSensor;
							}
							else if(_forceRight==null){
								_forceRight=s as ForceSensor;
								var t0:ForceTile=new ForceTile(_forceLeft,_forceRight);
								_mainView.tileView.addTile(t0);
							}
							break;
						case SensorType.PULSE:
							var t1:PulseTile=new PulseTile(s as PulseSensor);
							_mainView.tileView.addTile(t1);
							break;
						case SensorType.GPS_MODULE:
							_mainView.mapView.attachSensor(s as GPSModule);
							_mainView.tileView.addTile(new SpeedTile(s as GPSModule));
							break;
						case SensorType.ELECTRO_LYCRA:
							if(_elycraL==null){
								_elycraL=s as ElectroLycraSensor;
								if(_flexL!=null)
									_mainView.tileView.addTile(new PositionTile(_elycraL,_flexL,PositionTile.LEFT_LEG));
							}
							else if(_elycraR==null){
								_elycraR=s as ElectroLycraSensor;
								if(_flexR!=null)
									_mainView.tileView.addTile(new PositionTile(_elycraR,_flexR,PositionTile.RIGHT_LEG));
							}
							break;
						case SensorType.FLEX:
							if(_flexL==null){
								_flexL=s as FlexSensor;
								if(_elycraL!=null)
									_mainView.tileView.addTile(new PositionTile(_elycraL,_flexL,PositionTile.LEFT_LEG));
							}
							else if(_flexR==null){
								_flexR=s as FlexSensor;
								if(_elycraR!=null)
									_mainView.tileView.addTile(new PositionTile(_elycraR,_flexR,PositionTile.RIGHT_LEG));
							}
							break;
						case SensorType.MMG:
							if(_mmgL==null)
								_mmgL=s as MMGSensor;
							else
								_mmgR=s as MMGSensor;
							if(_mmgL!=null&&_mmgR!=null)
								_mainView.tileView.addTile(new MMGTile(_mmgL,_mmgR));
							break;
						case SensorType.ACCELEROMETER_X:
							if(_accelerometerX==null)
								_accelerometerX=s as AccelerometerXSensor;
							if(_accelerometerX!=null&&_accelerometerY!=null){
								var t5:AccelerometerTile=new AccelerometerTile(_accelerometerX,_accelerometerY);
								_mainView.tileView.addTile(t5);
							}
							break;
						case SensorType.ACCELEROMETER_Y:
							if(_accelerometerY==null)
								_accelerometerY=s as AccelerometerYSensor;
							if(_accelerometerX!=null&&_accelerometerY!=null){
								var t6:AccelerometerTile=new AccelerometerTile(_accelerometerX,_accelerometerY);
								_mainView.tileView.addTile(t6);
							}
							break;
						case SensorType.THERMISTOR:
							_mainView.tileView.addTile(new ThermistorTile(s as ThermistorSensor));
							break;
						case SensorType.GENERIC_SENSOR:
							var tn:GenericSensorTile=new GenericSensorTile(s as GenericSensor)
							_mainView.tileView.addTile(tn);
							break;
						default:
							throw new Error("Error: Unknown Sensor Type:"+s.sensorType.toString(16));
							break;
					}
				}
			}
			else
				throw new Error("Error: Second Device Configuration Packet Received");
		}
		
		private var _gotSensorPacket:Boolean=false;
		
		private function _updateSensors(dataPacket:DataMessage):void{
			if(!dataPacket.validateChecksum()){
				trace("Warning: Bad Checksum");
				return;
			}
			dataPacket.resetDataPointer();
			var time:Number=dataPacket.readUint32();
			for each(var sensor:ISensorType in _sensors){
				switch(sensor.dataFormat){
					case DataFormat.UInt8:
						sensor.addData(dataPacket.readUint8(),time);
						break;
					case DataFormat.UInt16:
						sensor.addData(dataPacket.readUint16(),time);
						break;
					case DataFormat.UInt32:
						sensor.addData(dataPacket.readUint32(),time);
						break;
					case DataFormat.String:
						sensor.addData(dataPacket.readString(),time);
				}
			}
		}
	}
}